#!/usr/bin/env python
# coding=UTF-8
import random
import logging
import json
import time
import urllib
import datetime

import config
import dao

import redisco
from redisco.containers import List, Hash

from tools import nsq_pub, json_encode, MaJiangCheck


def get_last_data(bid, uid, rid):
    all_player_data = []
    mj = ShaoYangMJ(rid, bid)
    for member in mj.members:
        p = Player(member, bid, rid)
        player_data = p.get_data()
        eat_list = []
        eat_data_list = player_data['eat']
        for eat_data in eat_data_list:
            eat_list.append(eat_data.split(","))
        player_data['eat'] = eat_list
        player_data['status'] = 1
        all_player_data.append(player_data)
    game_round = mj.room['game_round']
    all_round = mj.room['all_round']
    dealer = mj.room['dealer']
    status = mj.room['status']
    last_get_user = mj.room['last_get_user']
    last_put_user = mj.room['last_put_user']
    if last_put_user:
        last_player = last_put_user
    else:
        last_player = last_get_user
    last_card = mj.room['last_card']
    left_card = len(mj.current_card.members)
    pub_data = {"act":"get_last_data",
                "game_round":game_round, 
                "all_round":all_round, 
                "last_card":last_card, 
                "last_player":last_player,
                "left_card":left_card,
                "dealer":dealer,
                "status":status,
                "rid":rid,
                "all_player_data":all_player_data,
                }
    nsq_pub({"b":bid, "u":uid, "t":"game", "d":pub_data})
    tips_user = mj.tips_user
    if tips_user:
        if uid in tips_user:
            p = Player(uid, bid, rid)
            tips = p.tips.members
            eat_card_list = []
            bar_card = []
            if "dark_bar" in tips:
                bar_card = mj.check_init_dark_bar(p.current_card.members)
            elif "eat" in tips:
                eat_card_list = mj.get_eat_card(p.current_card.members, last_card)
            mj.notify_tips(uid, last_card, tips, bar_card, eat_card_list)
    else:
        nsq_pub({"b":bid, "u":uid, "t":"game", "d":{"act":"turn_put", "rid":rid, "uid":last_player}})
        
class Player():
    def __init__(self, uid, bid='', rid='', first=False):
        self.uid = uid
        self.bid = bid
        self.rid = rid
        if first:
            redisco.connection.delete("p:%s:%s:%s:current_card" % (bid, uid, rid))
            redisco.connection.delete("p:%s:%s:%s:out_card" % (bid, uid, rid))
            redisco.connection.delete("p:%s:%s:%s:dark_bar" % (bid, uid, rid))
            redisco.connection.delete("p:%s:%s:%s:white_bar" % (bid, uid, rid))
            redisco.connection.delete("p:%s:%s:%s:pair" % (bid, uid, rid))
            redisco.connection.delete("p:%s:%s:%s:eat" % (bid, uid, rid))
            redisco.connection.delete("p:%s:%s:%s" % (bid, uid, rid))
            redisco.connection.delete("p:%s:%s:%s:tips" % (bid, uid, rid))
            redisco.connection.delete("p:%s:%s:%s:bar_user" % (bid, uid, rid))
            redisco.connection.delete("p:%s:%s:%s:pair_bar_user" % (bid, uid, rid))
            self.score = Hash("p:%s:%s:%s" % (bid, uid, rid))
            self.score['score'] = 0
            self.score['win_score'] = 0
            self.score['put_flag'] = ''
            self.score['win_type'] = ''
            self.score['win_type_name'] = ''
            self.score['win_card'] = ''
        else:
            self.score = Hash("p:%s:%s:%s" % (bid, uid, rid))
        self.current_card = List("p:%s:%s:%s:current_card" % (bid, uid, rid))
        self.out_card = List("p:%s:%s:%s:out_card" % (bid, uid, rid))
        self.dark_bar = List("p:%s:%s:%s:dark_bar" % (bid, uid, rid))
        self.white_bar = List("p:%s:%s:%s:white_bar" % (bid, uid, rid))
        self.bar_user = List("p:%s:%s:%s:bar_user" % (bid, uid, rid))
        self.pair_bar_user = List("p:%s:%s:%s:pair_bar_user" % (bid, uid, rid))
        self.pair = List("p:%s:%s:%s:pair" % (bid, uid, rid))
        self.eat = List("p:%s:%s:%s:eat" % (bid, uid, rid))
        self.tips = List("p:%s:%s:%s:tips" % (bid, uid, rid))

    def clear(self):
        redisco.connection.delete("p:%s:%s:%s:current_card" % (self.bid, self.uid, self.rid))
        redisco.connection.delete("p:%s:%s:%s:out_card" % (self.bid, self.uid, self.rid))
        redisco.connection.delete("p:%s:%s:%s:dark_bar" % (self.bid, self.uid, self.rid))
        redisco.connection.delete("p:%s:%s:%s:white_bar" % (self.bid, self.uid, self.rid))
        redisco.connection.delete("p:%s:%s:%s:pair" % (self.bid, self.uid, self.rid))
        redisco.connection.delete("p:%s:%s:%s:eat" % (self.bid, self.uid, self.rid))
        redisco.connection.delete("p:%s:%s:%s" % (self.bid, self.uid, self.rid))
        redisco.connection.delete("p:%s:%s:%s:tips" % (self.bid, self.uid, self.rid))
        redisco.connection.delete("p:%s:%s:%s:bar_user" % (self.bid, self.uid, self.rid))
        redisco.connection.delete("p:%s:%s:%s:pair_bar_user" % (self.bid, self.uid, self.rid))
        
    def get_data(self):
        return {"uid":self.uid,
                "current_card":self.current_card.members,
                "out_card":self.out_card.members,
                "dark_bar":self.dark_bar.members,
                "white_bar":self.white_bar.members,
                "pair":self.pair.members,
                "eat":self.eat.members,
                "score":self.score['score'],
                "win_card":self.score['win_card'],
                }
        
class ShaoYangMJ():
    def __init__(self, rid, bid, dealer=None):
        self.rid = str(rid)
        self.bid = bid
        if dealer:
            redisco.connection.delete("r:%s:current_card" % rid)
            redisco.connection.delete("r:%s:out_card" % rid)
            redisco.connection.delete("r:%s:mid" % rid)
            redisco.connection.delete("r:%s:tips_user" % rid)
            redisco.connection.delete("r:%s:tips_act" % rid)
            redisco.connection.delete("r:%s:winner" % rid)
            self.room = Hash("r:%s" % rid)
            self.room['dealer'] = dealer
            self.room['last_get_user'] = dealer
            self.room['last_put_user'] = ''
            self.room['stop_pop_user'] = ''
            self.room['stop_pop_act'] = ''
            self.room['loser'] = ''
            self.room['last_card'] = ''
        else:
            self.room = Hash("r:%s" % rid)
        self.current_card = List("r:%s:current_card" % rid)
        self.out_card = List("r:%s:out_card" % rid)
        self.tips_user = List("r:%s:tips_user" % rid)
        self.tips_act = List("r:%s:tips_act" % rid)
        self.winner = List("r:%s:winner" % rid)
        l = List("r:%s:p" % rid)
        self.members = l.members
        
    def incr_mid(self):
        return redisco.connection.incr("r:%s:mid" % self.rid)

    def trans_card(self, all_card):
        res = []
        for c in all_card:
            res.append(int(c))
        res.sort()
        return res

    def get_horse(self, num, winner):
        seat_horse_card = [['101', '105', '109', '201', '205', '209', '301', '305', '309', '401', '405'],
                           ['102', '106', '202', '206', '302', '306', '402', '406'],
                           ['103', '107', '203', '207', '303', '307', '403', '407'],
                           ['104', '108', '204', '208', '304', '308', '404'],
                           ]
        
        horse_card = []
        dealer = self.room['dealer']
        dealer_seat = self.members.index(str(dealer))
        # 庄家座位
        winner_seat = self.members.index(str(winner))
        # 赢家的座位
        if self.room['game_type'] == 'hzmj':
            winner_seat_horse = seat_horse_card[0]
        else:
            winner_seat_horse = seat_horse_card[winner_seat - dealer_seat]
        # 该赢家对应座位的马牌列表
        current_card = self.current_card.members
        jk = self.room['joker']
        if jk:
            joker_list = jk.split(",")
        else:
            joker_list = []
        all_horse_card = current_card[:num]
        for card in all_horse_card:
            if card in winner_seat_horse or card in joker_list:
                horse_card.append(card)
        logging.info(u"获取马牌:num:%s,所有马牌:%s, 已中马牌:%s,种马数量 :%s" % (num, all_horse_card, horse_card, len(horse_card)))
        return all_horse_card, horse_card
    
    def get_jiang(self, all_card):
        res = []
        card = self.trans_card(all_card)
        for c in set(card):
            if card.count(c) >= 2:
                res.append(c)
        return res
    
    def get_n(self, all_card, jiang, joker=[]):
        n = 0
        res = []
        jiang = int(jiang)
        card = self.trans_card(all_card)
        card.sort()
        if jiang and card.count(jiang) >= 2:
            card.remove(jiang)
            card.remove(jiang)
            n += 1
        while card:
            c = card.pop(0)
            if card.count(c) >= 2:
                n += 1
                card.remove(c)
                card.remove(c)
                res.append([c, c, c])
            elif c > 400:
                break
            else:
                c2 = c + 1
                c3 = c + 2
                if c2 in card and c3 in card:
                    card.remove(c2)
                    card.remove(c3)
                    res.append([c, c2, c3])
                    n += 1
                else:
                    break
        return n
    
    def is_pinghu(self, all_card, has_n=0, win_type='put_win'):
        #jiang_list = self.get_jiang(all_card)
        #res = [0,]
        #for jiang in jiang_list:
        #    card = self.trans_card(all_card)
        #    n = self.get_n(card, jiang)
        #    res.append(n)
        #if max(res)+has_n >= 5:
        #    return 'pinghu'
        #return False
        mj = MaJiangCheck()
        res = mj.check_win(has_n, all_card)
        if res:
            return 'pinghu'
        return False
    
    def is_qixiaodui(self, all_card):
        '''七小对'''
        pair = 0
        card = self.trans_card(all_card)
        for c in set(card):
            if card.count(c) == 4:
                pair += 2
            elif card.count(c) == 2:
                pair += 1
        if pair == 7:
            return 'qixiaodui'
        return False
    
    def is_longqidui(self, all_card):
        '''龙七对'''
        pair = 0
        bomb = 0
        card = self.trans_card(all_card)
        for c in set(card):
            if card.count(c) == 4:
                bomb += 1
                pair += 2
            elif card.count(c) == 2:
                pair += 1
        if pair == 7 and bomb >= 1:
            return 'longqidui' 
        return False
    
    def is_pengpenghu(self, all_card, has_n=0):
        '''碰碰胡,AAABBBCCCDDD乱将'''
        res = [0]
        jiang_list = self.get_jiang(all_card)
        for jiang in jiang_list:
            card = self.trans_card(all_card)
            card.remove(jiang)
            card.remove(jiang)
            triple = 0
            for c in set(card):
                if card.count(c) == 3:
                    triple += 1
            res.append(triple+1)
        if max(res)+has_n >= 5:
            return 'pengpenghu'
        return False
    
    def is_qingyise(self, all_card):
        '''清一色:16'''
        card = self.trans_card(all_card)
        color = card[0]/100
        for c in set(card):
            if c/100 != color:
                return False
        if color == 4:
            return 'fengyise'
        return 'qingyise'
    
    def is_fengyise(self, all_card):
        '''风一色:24'''
        card = self.trans_card(all_card)
        for c in set(card):
            if c/100 != 4:
                return False
        return 'fengyise'
    
    def is_shisanyao(self, all_card):
        '''十三幺:24'''
        jiang_list = self.get_jiang(all_card)
        if len(jiang_list) != 1:
            return False
        jiang = jiang_list[0]
        card_list = ['11', '19', '21', '29', '31', '39', '41', '42', '43', '44', '45', '46', '47']
        if set(all_card) == set(card_list) and jiang in card_list:
            return 'shisanyao'
        return False
    
    def is_mengqing(self, white_bar, pair, eat):
        '''门清:4'''
        if white_bar or pair or eat:
            return False
        return 'mengqing'

    def check_init_dark_bar(self, current_card):
        # 检查初始手牌能否暗杠
        res = []
        for k in set(current_card):
            if current_card.count(k) == 4:
                res.append(k)
        return res
    
    def check_dark_bar(self, current_card, card=''):
        # 检查摸的牌能否暗杠
        if current_card.count(card) == 4:
            return True
        return False

    def check_bar(self, current_card, card=''):
        # 检查能否杠
        if current_card.count(card) == 3:
            return True
        return False

    def check_pair_bar(self, pair, card=''):
        # 检查碰过的牌是否摸到杠
        if pair.count(card) >= 1:
            return True
        return False
    
    def check_pair(self, current_card, card=''):
        # 检查能否碰牌
        if current_card.count(card) >= 2:
            return True
        return False
    
    def check_win(self, player, card=''):
        '''检查是否符合自模糊'''
        # 检查
        n = 0
        dark_bar = player.dark_bar.members
        white_bar = player.white_bar.members
        pair = player.pair.members
        eat = player.eat.members
        n += len(dark_bar)
        n += len(white_bar)
        n += len(pair)
        n += len(eat)
        current_card = player.current_card.members
        if card:
            current_card.append(card)
        logging.info(u"判断用户%s是否胡牌:%s" % (player.uid, str(current_card)))
        if len(current_card) != ((4 - n) * 3 + 2):
            logging.info(u"该玩家手牌相公不能胡牌:%s" % player.uid)
            return False
        if self.is_qixiaodui(current_card):
            return True
        elif self.is_shisanyao(current_card):
            return True
        elif self.is_pinghu(current_card, n, 'win'):
            return True
        return False
    
    def get_win_score(self, win_type_list):
        score = 0
        win_type_conf = {'shisanyao':{'name':u"十三幺", 'score':24},
                         'fengyise':{'name':u"风一色", 'score':24},
                         'longqidui':{'name':u"龙七对", 'score':16},
                         'qingyise_pengpenghu':{'name':u"清一色碰碰胡", 'score':16},
                         'qingyise_menqing':{'name':u"清一色门清", 'score':16},
                         'qingyise_qixiaodui':{'name':u"清一色七小对", 'score':16},
                         'qingyise':{'name':u"清一色", 'score':8},
                         'qixiaodui':{'name':u"七小对", 'score':8},
                         'pengpenghu':{'name':u"大对碰", 'score':8},
                         'menqing':{'name':u"门清", 'score':4},
                         'pinghu':{'name':u"自模胡", 'score':6},
                         'put_pinghu':{'name':u"接炮胡", 'score':6},
                         }
        win_type = win_type_list[0]
        return win_type_conf[win_type]['score']
    
    def trans_win_type(self, win_type_list):
        res = []
        win_type_conf = {'shisanyao':{'name':u"十三幺", 'score':24},
                         'fengyise':{'name':u"风一色", 'score':24},
                         'longqidui':{'name':u"龙七对", 'score':16},
                         'qingyise_pengpenghu':{'name':u"清一色碰碰胡", 'score':16},
                         'qingyise_menqing':{'name':u"清一色门清", 'score':16},
                         'qingyise_qixiaodui':{'name':u"清一色七小对", 'score':16},
                         'qingyise':{'name':u"清一色", 'score':8},
                         'qixiaodui':{'name':u"七小对", 'score':8},
                         'pengpenghu':{'name':u"大对碰", 'score':8},
                         'menqing':{'name':u"门清", 'score':4},
                         'pinghu':{'name':u"自模胡", 'score':6},
                         'put_pinghu':{'name':u"接炮胡", 'score':6},
                         }
        for win_type in win_type_list:
            res.append(win_type_conf[win_type]['name'])
        return res
    
    def get_win_type(self, player, card='', win_type='win'):
        n = 0
        dark_bar = player.dark_bar.members
        white_bar = player.white_bar.members
        pair = player.pair.members
        eat = player.eat.members
        n += len(dark_bar)
        n += len(white_bar)
        n += len(pair)
        n += len(eat)
        current_card = player.current_card.members
        if card:
            current_card.append(card)
        if len(current_card) != ((4 - n) * 3 + 2):
            logging.info(u"该玩家手牌相公不能胡牌:%s" % player.uid)
            return False
        shisanyao = self.is_shisanyao(current_card)
        if shisanyao:
            return [shisanyao]
        
        pinghu = self.is_pinghu(current_card, n)
        if not pinghu:
            return False
        fengyise = self.is_fengyise(current_card)
        if fengyise:
            return [fengyise]
        
        longqidui = self.is_longqidui(current_card)
        if longqidui:
            return [longqidui]
        all_card = []
        all_card.extend(current_card)
        if dark_bar:
            all_card.extend(dark_bar)
        if white_bar:
            all_card.extend(white_bar)
        if pair:
            all_card.extend(pair)
        if eat:
            for eat_card in eat:
                all_card.extend(eat_card.split(","))
        qingyise = self.is_qingyise(all_card)
        menqing = self.is_mengqing(white_bar, pair, eat)
        qixiaodui = self.is_qixiaodui(current_card)
        pengpenghu = self.is_pengpenghu(current_card, n)
        if qingyise:
            if menqing:
                return ['qingyise_menqing']
            elif qixiaodui:
                return ['qingyise_qixiaodui']
            elif pengpenghu:
                return ['qingyise_pengpenghu']
            return [qingyise]
        elif qixiaodui:
            return [qixiaodui]
        elif pengpenghu:
            return [pengpenghu]
        elif menqing:
            return [menqing]
        if win_type == 'win':
            return ['pinghu']
        return ['put_pinghu']
            
    def get_eat_card(self, all_card, card):
        '''获取可吃的牌'''
        card = int(card)
        if card > 400:
            return []
        c = card % 100
        n = card / 100
        res = []
        point_res = []
        if c == 9:
            point_res = [[7, 8]]
        elif c == 8:
            point_res = [[6, 7], [7, 9]]
        elif c == 7:
            point_res = [[5, 6], [6, 8], [8, 9]]
        elif c == 6:
            point_res = [[4, 5], [5, 7], [7, 8]]
        elif c == 5:
            point_res = [[3, 4], [4, 6], [6, 7]]
        elif c == 4:
            point_res = [[2, 3], [3, 5], [5, 6]]
        elif c == 3:
            point_res = [[1, 2], [2, 4], [4, 5]]
        elif c == 2:
            point_res = [[1, 3], [3, 4]]
        elif c == 1:
            point_res = [[2, 3]]
        for [s, e] in point_res:
            c1 = str(n*100+s)
            c2 = str(n*100+e)
            if c1 in all_card and c2 in all_card:
                res.append([c1, c2])
        return res
    
    def check_eat(self, all_card, card):
        '''判断能否吃card牌'''
        card = int(card)
        all_card = [int(x) for x in all_card]
        all_card.append(card)
        all_card.sort()
        if len(all_card) == 3 and (all_card[0]+1) == all_card[1] and (all_card[0]+2) == all_card[2]:
            return True
        return False
    
    def notify_put(self, uid):
        '''通知玩家出牌'''
        self.room['last_get_user'] = uid
        self.room['stop_pop_user'] = ""
        self.room['stop_pop_act'] = ""
        for member in self.members:
            nsq_pub({"b":self.bid, "u":str(member), "t":"game", "d":{"act":"turn_put", "rid":self.rid, "uid":uid}})
    
    def notify_tips(self, uid, card, tips, bar_card=[], eat_card=[]):
        #self.room['stop_pop_user'] = ""
        #self.room['stop_pop_act'] = ""
        nsq_pub({"b":self.bid, "u":str(uid), "t":"game", "d":{"act":"tips", "rid":self.rid, "uid":uid, "tips":tips, "card":card, "bar_card":bar_card, "eat_card":eat_card}})
    
    def start(self):
        self.room['status'] = 'start'
        w = [str(x) for x in range(101, 110)] * 4
        d = [str(x) for x in range(201, 210)] * 4
        t = [str(x) for x in range(301, 310)] * 4
        f = [str(x) for x in range(401, 408)] * 4
        random.shuffle(w)
        random.shuffle(d)
        random.shuffle(t)
        random.shuffle(f)
        player_cnt = len(self.members)
        init_left_card = 136 - player_cnt * 13 - 1
        all_card = w + d + t + f
        random.shuffle(all_card)
        
        game_type = self.room['game_type']
        dealer = self.room['dealer']
        game_round = self.room['game_round']
        all_round = self.room['all_round']
        dealer_seat = self.members.index(dealer)
        all_user_card = []
        for i in range(player_cnt):
            idex = (dealer_seat + i) % player_cnt
            uid = self.members[idex]
            player = Player(uid, self.bid, self.rid, True)
            card = []
            if i == 0:
                for i in range(14):
                    card.append(all_card.pop())
            else:
                for i in range(13):
                    card.append(all_card.pop())
            card.sort()
            all_user_card.append({"uid":uid, "current_card":card})
            player.current_card.clear()
            player.current_card.extend(card)
            
        mid = self.incr_mid()
        for member in self.members:
            nsq_pub({"b":self.bid, "u":member, "t":"game", "d":{"act":"game_start", "left_card":init_left_card, "rid":self.rid, "dealer":dealer, "game_round":game_round, "all_round":all_round, "all_user_card":all_user_card}})
        
        game_round = self.room['game_round']
        nsq_pub({"b":self.bid, "u":"", "t":"game", "d":{"act":"game_start", "game_round":game_round,"left_card":init_left_card, "rid":self.rid, "mid":mid, "dealer":dealer, "game_round":game_round, "all_round":all_round, "all_user_card":all_user_card}})
        
        self.room['last_get_user'] = dealer
        self.current_card.clear()
        self.current_card.extend(all_card)
        logging.info(u"房间rid:%s,game_round:%s,发牌结束" % (self.rid, self.room['game_round']))
        p = Player(dealer, self.bid, self.rid)
        win_flag = self.check_win(p, '')
        if win_flag:
            tips = ['win']
            win_card = p.current_card.members[-1]
            
            self.room['stop_pop_user'] = ""
            self.room['stop_pop_act'] = ""
            self.tips_user.append(dealer)
            self.tips_act.extend(tips)
            p.tips.extend(tips)
            self.notify_tips(dealer, win_card, tips, [], [])
        else:
            self.notify_put(dealer)
            
    def next_pop(self, uid=None, from_bar=False):
        # 发牌逻辑
        self.tips_act.clear()
        self.tips_user.clear()
        self.room['stop_pop_user'] = ""
        self.room['stop_pop_act'] = ""
        if not uid:
            last_get_user = self.room['last_get_user']
            logging.info("next_pop, last:%s" % last_get_user)
            last_player_seat = self.members.index(str(last_get_user))
            idx = (last_player_seat + 1) % len(self.members)
            uid = self.members[idx]
        
        left_card = len(self.current_card.members)
        horse_num = int(self.room['horse'])
        if left_card <= horse_num:
            logging.info(u"房间%s剩余牌数小于马牌数量，结束牌局" % (left_card, horse_num))
            self.game_over()
            return
        card = self.current_card.pop()
        if not card:
            logging.info("over===========")
            self.game_over()
            return
        self.room['last_get_user'] = uid
        self.room['last_card'] = card
        if from_bar:
            self.room['bar_get_card'] = card
        else: 
            self.room['bar_get_card'] = ''
            
        p = Player(uid, self.bid, self.rid)
        p.tips.clear()
        #检查漏胡标记, 摸牌后清除状态
        p_flag = p.score['flag']
        if p_flag == 'n':
            p.score['flag'] = ''
        tips = []
        bar_card = []
        win_type = self.check_win(p, card)
        if win_type:
            tips.append("win")
        
        current_card = p.current_card.members
        init_dark_bar = self.check_init_dark_bar(current_card)
        if self.check_bar(current_card, card):
            tips.append("dark_bar")
            bar_card.append(card)
        elif self.check_pair_bar(p.pair.members, card):
            tips.append("pair_bar")
            
        if init_dark_bar:
            tips.append("dark_bar")
            bar_card.extend(init_dark_bar)
        user_data = p.get_data()
        p.current_card.append(card)
        
        mid = self.incr_mid()
        left_card = len(self.current_card)
        for member in self.members:
            nsq_pub({"b":self.bid, "u":member, "t":"game", "d":{"act":"get_card", "left_card":left_card, "uid":uid, "card":card, "rid":self.rid}})
        
        game_round = self.room['game_round']
        nsq_pub({"b":self.bid, "u":"", "t":"game", "d":{"act":"get_card", "game_round":game_round,"left_card":left_card, "mid":mid, "uid":uid, "card":card, "rid":self.rid, "user_data":user_data}})
        
        if tips:
            self.tips_user.append(uid)
            self.tips_act.extend(tips)
            p.tips.extend(tips)
            self.notify_tips(uid, card, tips, bar_card)
        else:
            self.notify_put(uid)

    def put_card(self, uid, data):
        # 玩家出牌逻辑
        uid = str(uid)
        #是否重复发牌给客户端
        stop_pop_user = self.room['stop_pop_user']
        if stop_pop_user and stop_pop_user != str(uid):
            logging.error(u"玩家:%s有提示未处理,轮不到%s出牌" % (stop_pop_user, uid))
            get_last_data(self.bid, uid, self.rid)
            return
        last_put_user = self.room['last_put_user']
        if uid == last_put_user:
            logging.error(u"玩家:%s不能连续出牌" % (uid))
            get_last_data(self.bid, uid, self.rid)
            return
        card = data['card']
        p = Player(uid, self.bid, self.rid)
        curernt_card = p.current_card.members
        if curernt_card.count(card) == 0:
            logging.info(curernt_card)
            logging.error(u"出牌错误,该玩家没有该牌")
            get_last_data(self.bid, uid, self.rid)
            return
        
        #self.tips_act.clear()
        #self.tips_user.clear()
        
        p.out_card.append(card)
        p.current_card.remove(card)
        self.room['last_put_user'] = uid
        self.room['last_get_user'] = uid
        self.room['last_card'] = card
        p.score['put_flag'] = 'y'
        members = self.members
        player_cnt = len(members)
        mid = self.incr_mid()
        put_win_user = []
        #按照玩家座位顺序检查是否有胡牌可能
        user_seat = members.index(uid)
        tips = []
        from_bar = self.room['bar_get_card']
        self.room['bar_get_card'] = ''
        user_data = p.get_data()
        for i in range(player_cnt):
            idex = (user_seat + i) % player_cnt
            member = members[idex]
            if member != uid:
                member_player = Player(member, self.bid, self.rid)
                if from_bar:
                    if self.check_win(member_player, card):
                        put_win_user.append(member)
                        member_player.tips.append("put_win")
                win_card = []
            else:
                win_card = []
            nsq_pub({"b":self.bid, "u":member, "t":"game", "d":{"act":"put_card", "win_card":win_card, "card":card, "rid":self.rid, "uid":uid}})
        
        game_round = self.room['game_round']
        nsq_pub({"b":self.bid, "u":"", "t":"game", "d":{"act":"put_card", "game_round":game_round,"win_card":win_card, "mid":mid, "card":card, "rid":self.rid, "uid":uid, "user_data":user_data}})
        
        if put_win_user:
            #点炮胡的情况
            self.room['stop_pop_user'] = ""
            self.room['stop_pop_act'] = ""
            tips = ["put_win",]
            self.tips_user.extend(put_win_user)
            self.tips_act.extend(tips)
            for win_user in put_win_user:
                self.notify_tips(win_user, card, tips, [], [])
            return
        
        tips_user = self.check_put_tips(uid, card)
        if tips_user:
            return
        #所有提示都没有的情况,继续下家发牌
        self.next_pop()
            
    def check_put_tips(self, last_put_user='', card=''):
        if not last_put_user:
            last_put_user = self.room['last_put_user']
            last_put_player = Player(last_put_user, self.bid, self.rid)
            card = last_put_player.out_card.members[-1]
        
        members = self.members
        user_seat = members.index(last_put_user)
        next_idex = (user_seat + 1) % len(members)
        next_member = members[next_idex]
        tips_user = []
        eat_card_list = []
        for member in members:
            if member != last_put_user:
                member_player = Player(member, self.bid, self.rid)
                current_card = member_player.current_card.members
                tips = [] 
                if self.check_bar(current_card, card):
                    tips.append("bar")
                    tips.append("pair")
                elif self.check_pair(current_card, card):
                    tips.append("pair")
                
                if member == next_member:
                    eat_card_list = self.get_eat_card(current_card, card)
                    if eat_card_list:
                        tips.append("eat")
                else:
                    eat_card_list = []

                if tips:
                    tips_user.append(member)
                    self.tips_user.append(member)
                    self.tips_act.extend(tips)
                    member_player.tips.extend(tips)
                    self.notify_tips(member, card, tips, [], eat_card_list)
                    logging.info(u"房间%s玩家%s出牌%s,%s通知提示" % (self.rid, last_put_user, card, member))
        if tips_user:
            self.room['stop_pop_user'] = ""
            self.room['stop_pop_act'] = ""
        return tips_user
    
    def pass_card(self, uid, data):
        logging.info(u"有玩家pass:%s" % uid)
        tips_user = self.tips_user.members
        if uid not in tips_user:
            logging.error(u"房间:%s该用户没有提示操作不能pass:%s" % (self.rid, uid))
            return
        
        self.tips_user.remove(uid)
        p = Player(uid, self.bid, self.rid)
        p.tips.clear()
        if len(tips_user) - 1 == 0:
            tips_act = self.tips_act.members
            self.tips_act.clear()
            
            top_tips_user = self.room['stop_pop_user']
            if top_tips_user:
                #执行高优先级的操作
                top_tips_act = self.room['stop_pop_act']
                if 'put_win' == top_tips_act:
                    self.game_over()
                    return
                elif 'pair_bar_win' == top_tips_act:
                    self.game_over()
                    return
                elif 'eat' == top_tips_act:
                    top_player = Player(top_tips_user, self.bid, self.rid)
                    eat_data = json.loads(top_player.score['eat_data'])
                    self.do_eat(top_tips_user, eat_data)
                    return
                return
            else:
                if "win" in tips_act or "dark_bar" in tips_act or "pair_bar" in tips_act:
                    logging.info(u"房间%s 玩家%s摸牌后放弃操作:%s" % (self.rid, uid, str(tips_act)))
                    self.notify_put(uid)
                    return
                elif "put_win" in tips_act:
                    logging.info(u"房间%s put_win玩家%s全部都放弃杠后放炮胡牌,检查有无碰或杠或吃" % (self.rid, uid))
                    tips_user = self.check_put_tips()
                    if tips_user:
                        return
                    else:
                        if self.winner:
                            self.game_over()
                        else:
                            self.next_pop()
                elif "pair_bar_win" in tips_act:
                    logging.info(u"房间%s玩家%s全部都放弃pair_bar_win" % (self.rid, uid))
                    if self.winner:
                        self.game_over()
                    else:
                        last_get_user = self.room['last_get_user']
                        self.next_pop(last_get_user, from_bar=True)
                else:
                    self.next_pop()
        else:
            logging.info(u"房间:%s玩家%s pass, 等待其他玩家处理" % (self.rid, uid ))


    def dark_bar(self, uid, data):
        tips_user = self.tips_user.members
        if not tips_user:
            logging.error(u"目前没有提示, 不该%s操作" % uid)
            get_last_data(self.bid, uid, self.rid)
            return
        elif uid not in tips_user:
            logging.error(u"玩家%s有提示, 不该%s操作" % (str(tips_user), uid))
            get_last_data(self.bid, uid, self.rid)
            return
        
        card = data.get('card', '')
        p = Player(uid, self.bid, self.rid)
        current_card = p.current_card.members
        if not card:
            for k in set(current_card):
                if current_card.count(k) == 4:
                    card = k
        else:
            if not self.check_dark_bar(current_card, card):
                logging.error(u"请求错误,该用户不能杠牌:%s" % card)
                get_last_data(self.bid, uid, self.rid)
                return
        p.current_card.remove(card, 4)
        p.dark_bar.append(card)
        
        p.tips.clear()
        self.tips_user.clear()
        self.tips_act.clear()
        self.room['stop_pop_user'] = ""
        self.room['stop_pop_act'] = ""
        mid = self.incr_mid()
        for member in self.members:
            nsq_pub({"b":self.bid, "u":member, "t":"game", "d":{"act":"dark_bar", "card":card, "tips":[], "rid":self.rid, "uid":uid}})
        user_data = p.get_data()
        game_round = self.room['game_round']
        nsq_pub({"b":self.bid, "u":"", "t":"game", "d":{"act":"dark_bar", "game_round":game_round,"mid":mid, "card":card, "tips":[], "rid":self.rid, "uid":uid, "user_data":user_data}})
        
        self.next_pop(uid)
        
    def pair_bar(self, uid, data):
        # 碰过别的牌, 然后自己摸到一张，杠没有分
        # card = data['card']
        tips_user = self.tips_user.members
        if not tips_user:
            logging.error(u"目前没有提示, 不该%s操作" % uid)
            get_last_data(self.bid, uid, self.rid)
            return
        elif uid not in tips_user:
            logging.error(u"玩家%s有提示, 不该%s操作" % (str(tips_user), uid))
            get_last_data(self.bid, uid, self.rid)
            return

        p = Player(uid, self.bid, self.rid)
        card = p.current_card.members[-1]
        if not self.check_pair_bar(p.pair.members, card):
            logging.error(u"请求错误,该用户不能杠牌:%s" % card)
            get_last_data(self.bid, uid, self.rid)
            return
        self.room['stop_pop_user'] = ""
        self.room['stop_pop_act'] = ""
        p.current_card.remove(card)
        p.pair.remove(card)
        p.white_bar.append(card)
        
        p.pair_bar_user.append(uid)
        p.tips.clear()
        self.tips_user.clear()
        self.tips_act.clear()
        
        self.room['last_get_user'] = uid
        self.room['last_card'] = card
        mid = self.incr_mid()
        tips = []
        user_data = p.get_data()
        for member in self.members:
            nsq_pub({"b":self.bid, "u":member, "t":"game", "d":{"act":"pair_bar", "card":card, "tips":[], "rid":self.rid, "uid":uid}})
        
        game_round = self.room['game_round']
        nsq_pub({"b":self.bid, "u":"", "t":"game", "d":{"act":"pair_bar", "game_round":game_round,"mid":mid, "card":card, "tips":[], "rid":self.rid, "uid":uid, "user_data":user_data}})
        bar_win_user = []
        for member in self.members:
            if member != uid:
                member_player = Player(member, self.bid, self.rid)
                tips = []
                if self.room['grab_bar_win'] == 'y':
                    if self.check_win(member_player, card):
                        bar_win_user.append(member)
        
        if bar_win_user:
            #点炮胡的情况
            self.room['stop_pop_user'] = ""
            self.room['stop_pop_act'] = ""
            tips = ["pair_bar_win"]
            self.tips_user.extend(bar_win_user)
            self.tips_act.extend(tips)
            for win_user in bar_win_user:
                self.notify_tips(win_user, card, tips, [], [])
            return
        else:
            self.next_pop(uid, from_bar=True)
    
    def bar(self, uid, data):
        # 自己有三张,直接杠别人出的牌
        # card = data['card']
        # bar_uid = data['put_card_uid']
        
        tips_user = self.tips_user.members
        if not tips_user:
            logging.error(u"目前没有提示, 不该%s操作" % uid)
            get_last_data(self.bid, uid, self.rid)
            return
        elif uid not in tips_user:
            logging.error(u"玩家%s有提示, 不该%s操作" % (str(tips_user), uid))
            get_last_data(self.bid, uid, self.rid)
            return
        last_put_user = self.room['last_put_user']
        last_put_player = Player(last_put_user, self.bid, self.rid)
        
        card = last_put_player.out_card.members[-1]
        p = Player(uid, self.bid, self.rid)
        current_card = p.current_card.members
        if not self.check_bar(current_card, card):
            logging.error(u"请求错误,该用户不能杠牌:%s" % card)
            get_last_data(self.bid, uid, self.rid)
            return
        p.score['put_flag'] = 'y'
        card = last_put_player.out_card.pop()
        p.current_card.remove(card, 3)
        p.white_bar.append(card)
        p.bar_user.append(last_put_user)
        
        p.tips.clear()
        self.tips_user.clear()
        self.tips_act.clear()
        mid = self.incr_mid()
        self.room['last_get_user'] = uid
        self.room['last_card'] = card
        user_data = p.get_data()
        for member in self.members:
            nsq_pub({"b":self.bid, "u":member, "t":"game", "d":{"act":"bar", "card":card, "rid":self.rid, "uid":uid, "put_card_uid":last_put_user, "user_data":{}}})
        
        game_round = self.room['game_round']
        nsq_pub({"b":self.bid, "u":"", "t":"game", "d":{"act":"bar", "game_round":game_round,"mid":mid, "card":card, "rid":self.rid, "uid":uid, "put_card_uid":last_put_user, "user_data":user_data}})
        
        bar_win_user = []
        for member in self.members:
            if member != uid:
                member_player = Player(member, self.bid, self.rid)
                tips = []
                if member in tips_user:
                    member_player.tips.clear()
                if self.room['grab_bar_win'] == 'y':
                    if self.check_win(member_player, card):
                        bar_win_user.append(member)
        
        if bar_win_user:
            #点炮胡的情况
            self.room['stop_pop_user'] = ""
            self.room['stop_pop_act'] = ""
            tips = ["pair_bar_win"]
            self.tips_user.extend(bar_win_user)
            self.tips_act.extend(tips)
            for win_user in bar_win_user:
                self.notify_tips(win_user, card, tips, [], [])
            return
        else:
            self.next_pop(uid, from_bar=True)

    def pair(self, uid, data):
        tips_user = self.tips_user.members
        if not tips_user:
            logging.error(u"目前没有提示, 不该%s操作" % uid)
            get_last_data(self.bid, uid, self.rid)
            return
        elif uid not in tips_user:
            logging.error(u"玩家%s有提示, 不该%s操作" % (str(tips_user), uid))
            get_last_data(self.bid, uid, self.rid)
            return
        # card = data['card']
        # put_card_uid = data['put_card_uid']
        last_put_user = self.room['last_put_user']
        last_put_player = Player(last_put_user, self.bid, self.rid)
        card = last_put_player.out_card.members[-1]
        
        p = Player(uid, self.bid, self.rid)
        current_card = p.current_card.members
        if not self.check_pair(current_card, card):
            logging.error(u"请求错误,该用户不能碰牌:%s" % card)
            get_last_data(self.bid, uid, self.rid)
            return
        card = last_put_player.out_card.pop()
        p.score['put_flag'] = 'y'
        p.current_card.remove(card, 2)
        p.pair.append(card)
        
        self.tips_user.clear()
        self.tips_act.clear()
        p.tips.clear()
        
        user_data = p.get_data()
        mid = self.incr_mid()
        for member in self.members:
            if member in tips_user:
                member_player = Player(member, self.bid, self.rid)
                member_player.tips.clear()
            nsq_pub({"b":self.bid, "u":member, "t":"game", "d":{"act":"pair", "card":card, "rid":self.rid, "uid":uid, "put_card_uid":last_put_user, "user_data":{}}})
        
        game_round = self.room['game_round']
        nsq_pub({"b":self.bid, "u":"", "t":"game", "d":{"act":"pair", "game_round":game_round, "mid":mid, "card":card, "rid":self.rid, "uid":uid, "put_card_uid":last_put_user, "user_data":user_data}})
        self.room['last_get_user'] = uid
        self.room['stop_pop_user'] = ""
        self.room['stop_pop_act'] = ""
        self.notify_put(uid)


    def eat(self, uid, data):
        '''吃牌'''
        tips_user = self.tips_user.members
        if not tips_user:
            logging.error(u"目前没有提示, 不该%s操作" % uid)
            get_last_data(self.bid, uid, self.rid)
            return
        elif uid not in tips_user:
            logging.error(u"玩家%s有提示, 不该%s操作" % (str(tips_user), uid))
            get_last_data(self.bid, uid, self.rid)
            return
        last_put_user = self.room['last_put_user']
        last_put_player = Player(last_put_user, self.bid, self.rid)
        card = last_put_player.out_card.members[-1]
        
        p = Player(uid, self.bid, self.rid)
        current_card = p.current_card.members
        eat_card_list = self.get_eat_card(current_card, card)
        if not eat_card_list:
            logging.error(u"请求错误,该用户不能吃这张牌:%s" % card)
            get_last_data(self.bid, uid, self.rid)
            return
        if len(tips_user) > 1:
            p.score['eat_data'] = json_encode(data)
            self.room['stop_pop_user'] = uid
            self.room['stop_pop_act'] = "eat"
            return
        p.tips.clear()
        
        self.do_eat(uid, data)
    
    def do_eat(self, uid, data):
        '''吃牌'''
        last_put_user = self.room['last_put_user']
        last_put_player = Player(last_put_user, self.bid, self.rid)
        card = last_put_player.out_card.members[-1]
        
        p = Player(uid, self.bid, self.rid)
        current_card = p.current_card.members
        eat_card_list = self.get_eat_card(current_card, card)
        if not eat_card_list:
            logging.error(u"请求错误,该用户不能吃这张牌:%s" % card)
            get_last_data(self.bid, uid, self.rid)
            return
        
        eat_card = data['eat_card']
        c1 = eat_card[0]
        c2 = eat_card[1]
        if c1 not in current_card or c2 not in current_card or not self.check_eat(eat_card, card):
            logging.error(u"吃牌错误,该用户%s不能吃这张牌:%s" % (uid, card))
            get_last_data(self.bid, uid, self.rid)
            return
        self.tips_user.clear()
        self.tips_act.clear()
        
        card = last_put_player.out_card.pop()
        p.current_card.remove(eat_card[0], 1)
        p.current_card.remove(eat_card[1], 1)
        p.score['put_flag'] = 'y'
        eat_card_list = [c1, c2, card]
        eat_card_list.sort()
        p.eat.append(",".join(eat_card_list))
        mid = self.incr_mid()
        user_data = p.get_data()
        for member in self.members:
            nsq_pub({"b":self.bid, "u":member, "t":"game", "d":{"act":"eat", "card":card, "eat_card":eat_card_list, "rid":self.rid, "uid":uid, "put_card_uid":last_put_user, "user_data":{}}})
        
        game_round = self.room['game_round']
        nsq_pub({"b":self.bid, "u":"", "t":"game", "d":{"act":"eat", "game_round":game_round,"mid":mid, "card":card, "eat_card":eat_card_list, "rid":self.rid, "uid":uid, "put_card_uid":last_put_user, "user_data":user_data}})
        
        self.room['last_get_user'] = uid
        self.room['stop_pop_user'] = ""
        self.room['stop_pop_act'] = ""
        self.notify_put(uid)
        
    def win(self, uid, data):
        if self.room['status'] != 'start':
            logging.error(u"该轮游戏已结束")
            return
        tips_user = self.tips_user.members
        if not tips_user:
            logging.error(u"目前没有提示, 不该%s操作" % uid)
            get_last_data(self.bid, uid, self.rid)
            return
        elif uid not in tips_user:
            logging.error(u"玩家%s有提示, 不该%s操作" % (str(tips_user), uid))
            get_last_data(self.bid, uid, self.rid)
            return
        
        p = Player(uid, self.bid, self.rid)
        current_card = p.current_card.members
        card = current_card[-1]
        p.tips.clear()
        
        if not self.check_win(p, ''):
            logging.error(u"请求错误,该用户不能胡牌:%s" % card)
            get_last_data(self.bid, uid, self.rid)
            return
        
        self.winner.append(uid)
        
        self.room['stop_pop_user'] = ""
        self.room['stop_pop_act'] = ""
        
        member_len = len(self.members)
        win_type_list = self.get_win_type(p, '')
        
        score = self.get_win_score(win_type_list)
        win_type_list = self.trans_win_type(win_type_list)
        #base_score = 1
        if score > 12:
            score = 12
        win_score = score
        p.score['win_score'] = win_score
        p.score['win_type'] = 'win'
        p.score['win_type_name'] = u" ".join(win_type_list)
        p.score['win_card'] = card
        logging.info(u"用户%s自摸胡牌" % (uid))
        mid = self.incr_mid()
        user_data = p.get_data()
        for member in self.members:
            nsq_pub({"b":self.bid, "u":member, "t":"game", "d":{"act":"win", "card":card, "rid":self.rid, "uid":uid, "user_data":{}}})
        game_round = self.room['game_round']
        nsq_pub({"b":self.bid, "u":"", "t":"game", "d":{"act":"win", "game_round":game_round,"mid":mid, "card":card, "rid":self.rid, "uid":uid, "user_data":user_data}})
        
        self.game_over(uid, card)
        
    def put_win(self, uid, data):
        #点炮胡
        tips_user = self.tips_user.members
        if not tips_user:
            logging.error(u"目前没有提示, 不该%s操作" % uid)
            get_last_data(self.bid, uid, self.rid)
            return
        elif uid not in tips_user:
            logging.error(u"玩家%s有提示, 不该%s操作" % (str(tips_user), uid))
            get_last_data(self.bid, uid, self.rid)
            return
        last_put_user = self.room['last_put_user']
        last_put_player = Player(last_put_user, self.bid, self.rid)
        card = last_put_player.out_card.members[-1]
        logging.info("last_put_user:%s, card:%s" % (last_put_user, card))
        p = Player(uid, self.bid, self.rid)
        if not self.check_put_win(p, card):
            logging.error(u"请求错误,该用户不能胡牌:%s" % card)
            return
        
        self.winner.append(uid)
        self.room['stop_pop_user'] = ""
        self.room['stop_pop_act'] = ""
        all_horse_card = []
        data['card'] = card
        win_type_list = self.get_put_win_type(p, card)
        logging.info(u"点炮胡:%s" % str(win_type_list))
        members = self.members
        score = self.get_win_score(win_type_list)
        win_score = score
        logging.info(u"房间:%s用户%s点炮胡" % (self.rid, uid))
        win_type_list = self.trans_win_type(win_type_list)
        logging.info(u"点炮胡:%s" % str(win_type_list))
        #grab_bar_duty = self.room['grab_bar_duty']
        p.score['win_score'] = win_score
        p.score['win_type'] = 'put_win'
        p.score['win_type_name'] = u" ".join(win_type_list)
        p.score['win_card'] = card
        self.room['loser'] = last_put_user
        user_data = p.get_data()
        mid = self.incr_mid()
        for member in members:
            nsq_pub({"b":self.bid, "u":member, "t":"game", "d":{"act":"win", "mid":mid, "card":card, "rid":self.rid, "uid":uid, "user_data":{}}})
        game_round = self.room['game_round']
        nsq_pub({"b":self.bid, "u":"", "t":"game", "d":{"act":"win", "game_round":game_round, "mid":mid, "card":card, "rid":self.rid, "uid":uid, "user_data":user_data}})
        if len(self.winner.members) == len(tips_user):
            self.game_over()
    
    def pair_bar_win(self, uid, data={}):
        # 抢杠胡,杠家全包,退还之前杠的分数
        tips_user = self.tips_user.members
        tips_act = self.tips_act.members
        if not tips_user:
            logging.error(u"目前没有提示, 不该%s操作" % uid)
            get_last_data(self.bid, uid, self.rid)
            return
        elif uid not in tips_user:
            logging.error(u"玩家%s有提示, 不该%s操作" % (str(tips_user), uid))
            get_last_data(self.bid, uid, self.rid)
            return
        elif 'pair_bar_win' not in tips_act:
            logging.error(u"玩家%s有提示, 不该%s操作" % (str(tips_user), uid))
            get_last_data(self.bid, uid, self.rid)
            return
        
        #card = data['card']
        bar_uid = self.room['last_get_user']
        bar_player = Player(bar_uid, self.bid, self.rid)
        white_bar_member = bar_player.white_bar.members
        if white_bar_member:
            card = white_bar_member[-1]
        else:
            card = data.get("card", "")
        p = Player(uid, self.bid, self.rid)
        if not self.check_win(p, card):
            logging.error(u"请求错误,该用户不能胡牌:%s" % card)
            return
        
        self.winner.append(uid)
        all_horse_card = []
        horse_card = []
        horse_num = 0
        horse = self.room['horse']
        if horse:
            horse = int(horse)
            all_horse_card, horse_card = self.get_horse(horse, uid)
            horse_num = len(horse_card)
        else:
            horse = 0
        win_type_list = self.get_win_type(p, card)
        self.room['stop_pop_user'] = ""
        self.room['stop_pop_act'] = ""
        score = self.get_win_score(win_type_list)
        member_len = len(self.members)
        win_score = score
        win_type_list = self.trans_win_type(win_type_list)
        logging.info(u"用户%s抢杠胡,中%s马,得%s分" % (uid, horse_num, win_score))
        p.score['win_score'] = win_score
        p.score['win_type'] = 'pair_bar_win'
        p.score['win_type_name'] = u" ".join(win_type_list)
        p.score['win_card'] = card
        self.room['loser'] = bar_uid
        
        user_data = p.get_data()
        mid = self.incr_mid()
        for member in self.members:
            nsq_pub({"b":self.bid, "u":member, "t":"game", "d":{"act":"win", "mid":mid, "card":card, "rid":self.rid, "uid":uid, "user_data":{}}})
        game_round = self.room['game_round']
        nsq_pub({"b":self.bid, "u":"", "t":"game", "d":{"act":"win", "game_round":game_round, "mid":mid, "card":card, "rid":self.rid, "uid":uid, "user_data":{}}})
        if len(self.winner.members) == len(tips_user):
            self.game_over()

    def game_over(self, from_dissmiss=False):
        all_horse_card = []
        horse_card = []
        horse_num = 0
        horse = self.room['horse']
        winner_list = self.winner.members
        if horse:
            horse = int(horse)
            if len(winner_list) > 1:
                horse_uid = self.room['loser']
            else:
                horse_uid = winner_list[0]
            all_horse_card, horse_card = self.get_horse(horse, horse_uid)
            horse_num = len(horse_card)
        else:
            horse = 0
        horse_score = horse_num 
        #计算每个玩家的分数
        all_players = {}
        for member in self.members:
            member_player = Player(member, self.bid, self.rid)
            all_players[member] = member_player
        if winner_list:
            if len(winner_list) > 1:
                #抢杠或点炮
                loser = self.room['loser']
                #loser_player = Player(loser, self.bid, self.rid)
                loser_player = all_players[loser]
                for winner in winner_list:
                    winner_player = Player(winner, self.bid, self.rid)
                    win_score = int(winner_player.score['win_score']) + horse_score
                    loser_player.score['score'] = int(loser_player.score['score']) - win_score*3
            else:
                winner = winner_list[0]
                #winner_player = Player(winner, self.bid, self.rid)\
                winner_player = all_players[winner]
                win_type = winner_player.score['win_type']
                win_score = int(winner_player.score['win_score']) + horse_score
                winner_player.score['score'] = win_score * 3
                if win_type  == 'win':
                    #自摸三家扣钱
                    for member in self.members:
                        if member != winner:
                            #member_player = Player(member, self.bid, self.rid)
                            member_player = all_players[member]
                            member_player.score['score'] = int(member_player.score['score']) - win_score
                else:
                    #抢杠或点炮的点炮者包其他三家
                    loser = self.room['loser']
                    loser_player = Player(loser, self.bid, self.rid)
                    loser_player.score['score'] = int(loser_player.score['score']) - win_score*3
            
            #计算杠的分数
            for member in self.members:
                #member_player = Player(member, self.bid, self.rid)
                member_player = all_players[member]
                dark_bar = len(member_player.dark_bar.members)
                pair_bar_user = len(member_player.pair_bar_user.members)
                if dark_bar or pair_bar_user:
                    bar_score = dark_bar*2 + pair_bar_user
                    member_player.score['score'] = int(member_player.score['score']) + bar_score*3
                    for mm in self.members:
                        if mm != member:
                            mm_player = Player(mm, self.bid, self.rid)
                            mm_player.score['score'] = int(mm_player.score['score']) - bar_score
                bar_score = 0
                for bar_user in member_player.bar_user.members:
                    #bar_player = Player(bar_user, self.bid, self.rid)
                    bar_player = all_players[bar_user]
                    bar_player.score['score'] = int(bar_player.score['score']) - 3
                    bar_score += 3
                if bar_score:
                    member_player.score['score'] = int(member_player.score['score']) + bar_score
        
        self.room['status'] = 'over'
        self.room['stop_pop_user'] = ''
        self.room['stop_pop_act'] = ''
        self.room['last_put_user'] = ''
        self.room['last_get_user'] = ''
        game_round = int(self.room['game_round'])
        all_round = int(self.room['all_round'])
        
        dealer = self.room['dealer']
        if len(winner_list)>1:
            self.room['dealer'] = self.room['loser']
        elif len(winner_list) == 1:
            self.room['dealer'] = winner_list[0]
        
        room_left_card = len(self.current_card.members)
        gid = self.room['gid']
        match_id = self.room['mid']
        if not match_id:
            match_id = 0
        db = dao.Game_DB()
        rules = {}
        if gid:
            rows = db.game_rule(gid)
        else:
            rows = db.room_rule(self.rid)
            gid = ""
        for row in rows:
            k = row['param']
            v = row['value']
            rules[k] = v
            
        if game_round >= all_round or from_dissmiss:
            room_over = 'y'
        else:
            room_over = 'n'
        card = self.room['last_card']
        mid = self.incr_mid()
        player_card = {}
        for member in self.members:
            #member_player = Player(member, self.bid, self.rid)
            member_player = all_players[member]
            p_data = member_player.get_data()
            del p_data['out_card']
            if member in winner_list:
                p_data['is_winner'] = 'y'
                is_win = 1
            else:
                p_data['is_winner'] = 'n'
                is_win = 0
            if member == dealer:
                is_dealer = 'y'
            else:
                is_dealer = 'n'
            p_data['is_dealer'] = is_dealer
            score = int(p_data['score'])
            db.update_player(self.rid, member, score, 0)
            db.commit()
            player_info = db.get_player(self.rid, member)
            p_data['user_score'] = player_info['score']
            player_card[member] = p_data
            
            dark_bar = p_data['dark_bar']
            white_bar = p_data['white_bar']
            db.add_mj_room_log(match_id, gid, self.rid, game_round, member, score, len(white_bar), len(dark_bar), horse, is_dealer, is_win, 0, '')
            db.commit()
        
        game_type = self.room['game_type']
        game_type_name = config.GAME_TYPE_NAME[game_type]
        for member in self.members:
            pub_data = {"b":self.bid, "u":member, "t":"game", "d":{"act":"game_over", "game_type_name":game_type_name, "room_left_card":room_left_card, "gid":gid, "rules":rules, "room_over":room_over, "dealer":dealer, "game_round":game_round, "player_card":player_card, "mid":mid, "winner_list":winner_list, "rid":self.rid, "all_horse_card":all_horse_card, "horse_card":horse_card, "horse_num":horse_num}}
            nsq_pub(pub_data)
            db.save_game_over(self.rid, game_round, "game_over", member, urllib.quote(json_encode(pub_data).encode("utf-8")))
            db.commit()
            
        if room_over == 'y':
            self.dismiss()
        else:
            self.room['game_round'] = game_round + 1
            
            
    def dismiss(self, act='room_over'):
        db = dao.Game_DB()
        player_data = {}
        player_stat = []
        if not self.room['status']:
            logging.error(u"房间结束,未开始:%s" % self.rid)
            deduct_flag = False
            winner = ""
            for uid in self.members:
                player_stat.append({"uid":uid,"horse":0,"dark_bar":0,"white_bar":0,"score":0,"win_num":0, "is_best":"n"})
        else:
            p_stat = db.player_stat(self.rid)
            #logging.info(p_stat)
            for ps in p_stat:
                ps['horse'] = int(ps['horse'])
                ps['dark_bar'] = int(ps['dark_bar'])
                ps['white_bar'] = int(ps['white_bar'])
                ps['score'] = int(ps['score'])
                ps['win_num'] = int(ps['win_num'])
                ps['is_best'] = 'n'
                player_data[str(ps['uid'])] = ps
            deduct_flag = True
            if p_stat and p_stat[-1]['win_num'] > 0:
                winner = p_stat[-1]['uid']
            else:
                winner = ""
            # 排序最后一家为大赢家
            player_stat = p_stat
        
        match_id = self.room['mid']
        if not match_id:
            match_id = 0
        gid = self.room['gid']
        if not gid:
            gid = 0
        for ps in player_stat:
            if ps['uid'] == winner:
                is_best = 'y'
            else:
                is_best = 'n'
            ps['is_best'] = is_best
            if gid:
                db.add_room_stat(match_id, gid, self.rid, ps['uid'], ps['score'], is_best)
                db.commit()
            
        room_info = db.get_room(self.rid, self.bid)
        admin = room_info['admin']
        end_time = time.strftime("%Y-%m-%d %H:%M:%S")
        for member in self.members:
            if not member:
                continue
            pub_data = {"b":self.bid, "u":member, "t":"game", "d":{"act":"room_over", "rid":self.rid, "end_time":end_time, "player_stat":player_stat, "winner":winner, "admin":admin}}
            nsq_pub(pub_data)
            db.save_game_over(self.rid, 0, "room_over", member, json_encode(pub_data))
            db.commit()
        db.dismiss_room(self.rid)
        db.commit()
        game_type = self.room['game_type']
        if match_id or gid:
            nsq_pub({"b":self.bid, "u":"", "t":"game", "d":{"game_type":game_type, "match_id":match_id, "gid":gid, "act":"room_over", "rid":self.rid, "player_stat":player_stat, "winner":winner, "admin":admin}}, "match_club")
            
        if deduct_flag:
            card = room_info['card']
            db.deduct_card(self.bid, admin, card)
            nsq_pub({"act":"deduct_card", "bid":self.bid, "uid":admin, "card":card, "rid":self.rid}, "total")
            logging.info(u"房间%s解散成功,扣除房卡, bid:%s,uid:%s,card:%s" % (self.rid, self.bid, admin, card))
        else:
            logging.info(u"房间%s解散成功,游戏无需扣房卡" % self.rid)

        for member in self.members:
            member_player = Player(member, self.bid, self.rid)
            member_player.clear()
            
        redisco.connection.delete("r:%s:current_card" % self.rid)
        redisco.connection.delete("r:%s:out_card" % self.rid)
        redisco.connection.delete("r:%s" % self.rid)
        redisco.connection.delete("r:%s:mid" % self.rid)
        redisco.connection.delete("r:%s:p" % self.rid)
        redisco.connection.delete("r:%s:tips_user" % self.rid)
        redisco.connection.delete("r:%s:tips_act" % self.rid)
        redisco.connection.delete("r:%s:winner" % self.rid)
        